#pragma once

#include "thread.hpp"
#include "lockGuard.hpp"
#include "log.hpp"
#include <mutex>

const int g_default_num = 3;

template <class T>
class ThreadPool
{
public:
    pthread_mutex_t* getMutex()
    {
        return &lock_;
    }
    void waitCond()
    {
        pthread_cond_wait(&cond_, &lock_);
    }
    bool isEmpty()
    {
        return task_queue_.empty();
    }

private: // 私有构造，删除拷贝构造和赋值重载
    ThreadPool(int thread_num = g_default_num) // 初始化后，就已经有了对象，也有了this指针
        :num_(thread_num)
    {
        pthread_mutex_init(&lock_, nullptr);
        pthread_cond_init(&cond_, nullptr);
        for (int i = 0; i < num_; i++)
        {
            threads_.push_back(new Thread(i + 1, routine, this) ); // 通过传入this指针就可以拿到ThreadPool中的task_queue
        }
    }
    ThreadPool(const ThreadPool<T>&) = delete;
    const ThreadPool<T> operator=(const ThreadPool<T>& ) = delete;

public:
    static ThreadPool<T>* getThreadPool(int num = g_default_num)
    {
        // 只有第一次为空的时候才创建，如果不为空直接返回thread_ptr，这样指针就只有一个
        if (nullptr == thread_ptr)
        {
            //lockGuard lockguard(&mutex);
            unique_lock<mutex> lock(mutex);
            if (nullptr == thread_ptr)
            {
                thread_ptr = new ThreadPool<T>(num);
            }
        }
        return thread_ptr;
    }

    void run()
    {
        for (auto& iter : threads_)
        {
            iter->start();
            cout << iter->name() << "启动成功" << endl;
            // logMessage(NORMAL, "%s%s", iter->name().c_str(), "启动成功");
        }
    }

    // 去掉this指针
    // 消费的过程
    static void* routine(void* args)
    {
        ThreadData* td = (ThreadData*)args;
        ThreadPool<T>* tq = (ThreadPool<T>*)td->args_; // 去掉this指针就无法访问成员方法了，通过创建线程的时候传入this拿到线程池对象
        while (true)
        {
            T task;
            {
                lockGuard lockguard(tq->getMutex());  // 加锁
                while (tq->isEmpty()) tq->waitCond(); // 检测

                // 读取任务
                task = tq->getTask();
            }
            // 仿函数
            cout << td->name_ << ", 消费者：" << task._x << " + " << task._y << " = " << task() << endl;
            
            // logMessage(NORMAL, "%s, %d + %d = %d", td->name_.c_str(), task._x, task._y, task());
            
            sleep(1);
        }
    }
    void pushTask(const T& task)
    {
        lockGuard lockguard(&lock_);
        task_queue_.push(task);
        pthread_cond_signal(&cond_);
    }
    T getTask()
    {
        T t = task_queue_.front();
        task_queue_.pop();
        return t;
    }
    void joins()
    {
        for (auto& iter : threads_)
        {
            iter->join();
        }
    }
    ~ThreadPool()
    {
        for (auto& iter : threads_)
        {
            delete iter;
        }
        pthread_mutex_destroy(&lock_);
        pthread_cond_destroy(&cond_);
    }
private:
    vector<Thread*> threads_;
    int num_;
    
    static ThreadPool<T>* thread_ptr; // 单例模式
    static pthread_mutex_t mutex;

    queue<T> task_queue_;  // 任务队列
    pthread_mutex_t lock_; // 互斥锁
    pthread_cond_t cond_;  // 条件变量
};

template<class T>
ThreadPool<T>* ThreadPool<T>::thread_ptr = nullptr;

template<class T>
pthread_mutex_t ThreadPool<T>::mutex = PTHREAD_MUTEX_INITIALIZER; 